﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using StorageAbstraction;
using System.Configuration;
using System.IO;
using StorageAbstraction.Tables;

namespace CloudVideoConverter
{
    public partial class fMain : Form
    {
        private StorageSubsystem _sSytem;
        private int _numOfTicksPassed = 0;
        private Guid _currentTaskId;
        private BackgroundWorker _worker;

        public fMain()
        {
            InitializeComponent();
            this.Initialzie();
        }

        private void Initialzie()
        {
            string systemContainerName = ConfigurationManager.AppSettings["SystemContainer"];
            string requestContainerName = ConfigurationManager.AppSettings["RequestContainer"];
            string responseContainerName = ConfigurationManager.AppSettings["ResponseContainer"];
            string requestQueueName = ConfigurationManager.AppSettings["RequestQueue"];
            string connStr = ConfigurationManager.AppSettings["StorageClientAccount"];
            this._sSytem = new 
                StorageSubsystem(
                connStr, 
                requestQueueName,
                requestContainerName, 
                responseContainerName, 
                systemContainerName);
            this._worker = new System.ComponentModel.BackgroundWorker();
            this._worker.DoWork += new System.ComponentModel.DoWorkEventHandler(Worker_DoWork);
            this._worker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(Worker_RunWorkerCompleted);
        }

        #region EventHandlers

        void Worker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            BackGroundWorkerMessage bmsg = e.Result as BackGroundWorkerMessage;
            switch (bmsg.Type)
            {
                case MessageType.RequestWork:
                    bmsg.SaveToPath = string.Empty;
                    this._currentTaskId = bmsg.TaskId;
                    this.UpdateStatusText("File Uploaded! Waiting for result ...");
                    //spawn the worker to check for response
                    BackGroundWorkerMessage bgwm = new BackGroundWorkerMessage();
                    bgwm.TaskId = this._currentTaskId;
                    bgwm.Type = MessageType.GetVideoTaskMessage;
                    this._worker.RunWorkerAsync(bgwm);
                    break;
                case MessageType.ResponseWork:
                    this.UpdateStatusText(string.Format("File {0} saved to {1}", bmsg.ResponseMessage.BlobName, bmsg.SaveToPath));
                    this.SetEnabledState(true);
                    break;
                case MessageType.GetVideoTaskMessage:
                    CompletedTaskEntry vmsg = bmsg.ResponseMessage;
                    this.UpdateStatusText("Result Got! Downloading file ...");
                    if (vmsg != null)
                    {
                        saveToFolder.ShowDialog();
                        if (!string.IsNullOrEmpty(saveToFolder.SelectedPath))
                        {
                            BackGroundWorkerMessage bgwmDownload = new BackGroundWorkerMessage();
                            bgwmDownload.Type = MessageType.ResponseWork;
                            bgwmDownload.ResponseMessage = vmsg;
                            bgwmDownload.SaveToPath = saveToFolder.SelectedPath;
                            this._worker.RunWorkerAsync(bgwmDownload);
                        }
                    }
                    break;
            }
        }

        /// <summary>
        /// Handles the work by Background worker
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            BackGroundWorkerMessage bmsg = e.Argument as BackGroundWorkerMessage;
            switch (bmsg.Type)
            {
                case MessageType.RequestWork:
                    using (FileStream fs = File.OpenRead(bmsg.FileName))
                    {
                        bmsg.TaskId = this._sSytem.UploadRequestFile(fs, bmsg.SaveToPath);
                    }
                    e.Result = bmsg;
                    break;
                case MessageType.ResponseWork:
                    this._sSytem.DownloadTask(bmsg.ResponseMessage, bmsg.SaveToPath);
                    e.Result = bmsg;
                    break;
                case MessageType.GetVideoTaskMessage:
                    CompletedTaskEntry vmsg = null;
                    while (vmsg == null)
                    {
                        vmsg = this._sSytem.GetTaskCompleteMessage(this._currentTaskId);
                        // sleep 2 seconds
                        System.Threading.Thread.Sleep(2000);
                    }
                    bmsg.ResponseMessage = vmsg;
                    e.Result = bmsg;
                    break;
            }
        }

        private void btnBrowseInput_Click(object sender, EventArgs e)
        {
            inputFileDialog.ShowDialog();
            if (File.Exists(inputFileDialog.FileName))
            {
                this.pBarWorking.Enabled = true;
                this.pBarWorking.Visible = true;
                BackGroundWorkerMessage bgwm = new BackGroundWorkerMessage();
                bgwm.FileName = inputFileDialog.FileName;
                bgwm.SaveToPath = inputFileDialog.FileName.Substring(inputFileDialog.FileName.LastIndexOf("\\") + 1);
                bgwm.Type = MessageType.RequestWork;
                this.UpdateStatusText("Uploading File...");
                this.SetEnabledState(false);
                this._worker.RunWorkerAsync(bgwm);
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Sets the Enabled state of browse button and progress bar
        /// </summary>
        /// <param name="isEnabled">bool</param>
        private void SetEnabledState(bool isEnabled)
        {
            this.btnBrowseInput.Enabled = isEnabled;
            this.pBarWorking.Visible = !isEnabled;
        }

        /// <summary>
        /// Updates the status bar text with informational message
        /// </summary>
        /// <param name="txt"></param>
        private void UpdateStatusText(string txt)
        {
            this.lblStatus.Text = txt;
        }
        #endregion
    }
}
